﻿#include "../../libcat/include/cat-module.hpp"
#include "../../libcat/include/util/json.h"
#include<fstream>

namespace {

	int windowWidth = 0, windowHeight = 0;
	int WIDTH = 0, HEIGHT = 0;
	float scale = 0; 
	static bool flag = true;

	char* FileAsBytes(const char* path)
	{
#if _WIN64

		//fix open wchar file path
		int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
		wchar_t* wstr = new wchar_t[wchars_num];
		MultiByteToWideChar(CP_UTF8, 0, path, -1, wstr, wchars_num);

		int size = 0;
		struct _stat64 statBuf;
		if (_wstat64(wstr, &statBuf) == 0)
		{
			size = statBuf.st_size;
		}
		else {
			size = 0;
		}
#else
		int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
		wchar_t* wstr = new wchar_t[wchars_num];
		MultiByteToWideChar(CP_UTF8, 0, path, -1, wstr, wchars_num);

		int size = 0;
		struct _stat32 statBuf;
		if (_wstat32(wstr, &statBuf) == 0) {
			size = statBuf.st_size;
		}
		else {
			size = 0;
		}
#endif // X64
		std::fstream file;
		char* buf = new char[size];

		file.open(wstr, std::ios::in | std::ios::binary);
		if (!file.is_open())
		{
			return NULL;
		}
		file.read(buf, size);
		file.close();
		delete wstr;
		return buf;
	}

	cat_data_t* data_create_from_json(const char* json_string)
	{
		cat_data* data = new cat_data;

		JSONCPP_STRING error;
		Json::CharReaderBuilder json_builder;
		Json::Value root;
		Json::CharReader* json_reader = json_builder.newCharReader();
		bool parsingSuccessful = json_reader->parse(json_string, json_string + strlen(json_string), &root, &error);

		if (parsingSuccessful) {
			data->json = root;
		}
		else {
			blog(LOG_ERROR,
				"cat-data.cpp: [cat_data_create_from_json] "
				"Failed reading json string %s",
				error.c_str());
			free(data);
			data = NULL;
		}
		delete json_reader;

		return data;
	}

	cat_data_t* data_create_from_json_file(const char* json_file)
	{
		char* file_data = FileAsBytes(json_file);
		cat_data_t* data = NULL;

		if (file_data) {
			data = data_create_from_json(file_data);
			delete file_data;
		}
		else {
			blog(LOG_WARNING, "cat-data.cpp: [cat_data_create_from_json_file] "
				"Failed opening file %s", json_file);
		}

		return data;
	}

	bool WriteJsonFile(Json::Value const& root, const char* path)
	{
		std::ofstream os;
		os.open(path, std::ios::out | std::ios::trunc);
		if (!os.good()) {
			os.close();
			return false;
		}
		Json::StreamWriterBuilder builder;
		std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
		writer->write(root, &os);
		os.close();
		return true;
	}

	bool data_write_json_file(cat_data_t* data, const char* json_file)
	{
		return WriteJsonFile(data->json, json_file);
	}
}

void* Init(cat_data_t* settings) {
	
	cat_data *cfg = data_create_from_json_file("config-scale.json");
	scale = cfg->json["windows_scale"].asFloat();
	delete cfg;

	WIDTH = settings->json["decoration"]["window_size"][0].asInt();
	HEIGHT = settings->json["decoration"]["window_size"][1].asInt();

	windowWidth = WIDTH * scale;
	windowHeight = HEIGHT * scale;

	int reWidth, reHeight;

	if (WIDTH != windowWidth && WIDTH > 0) {
		reWidth = windowWidth;
		reHeight = windowWidth * HEIGHT / WIDTH;
	}
	else if (HEIGHT != windowHeight && HEIGHT > 0)
	{
		reWidth = windowHeight * WIDTH / HEIGHT;
		reHeight = windowHeight;
	}
	else {
		reWidth = WIDTH;
		reHeight = HEIGHT;
	}

	windowWidth = reWidth;
	windowHeight = reHeight;

	return settings;
}

void* Update(cat_data_t* settings) {
	
	return settings;
}

void* Release() {
	cat_data* cfg = data_create_from_json_file("config-scale.json");
	cfg->json["windows_scale"] = scale;
	data_write_json_file(cfg,"config-scale.json");
	delete cfg;
	return NULL;
};


void* Run(void* _window) {

	cat_window* cwindow = (cat_window*)_window;

	if (flag) {
		flag = false;
		cat_resize_window(cwindow, windowWidth, windowHeight);
	}
	scale = static_cast<float>(cwindow->window->getSize().x) /static_cast<float>( WIDTH);

	return _window;
};

CAT_DECLARE_MODULE()
bool cat_module_load() {
	cat_source_info a{};
	a.id = -2;
	a.type = CAT_SOURCE_TYPE_INPUT;
	a.Init = Init;
	a.Update = Update;
	a.Release = Release;
	a.Run = Run;

	cat_register_source(&a);
	return true;
}
